#include <windows.h>
#include <tlhelp32.h>
#include <psapi.h>
#include <shlwapi.h>
#include <tchar.h>
#include <iostream>
#include <fstream>
#include <vector>
#include <string>
#include <ctime>
#include <algorithm>
#include <locale.h>
#include <iostream>

// 程序版本信息
const std::wstring APP_VERSION = L"1.0.0";
const std::wstring APP_NAME = L"UToolBox Launcher";

// 全局变量声明
bool g_verbose = false;         // 详细模式标记（全局）
bool g_consoleNeeded = false;   // 控制台需求标记（全局）

// 全局日志配置
namespace LogConfig {
bool enabled = false;         // 日志默认不输出
std::wstring path;            // 日志路径
static bool isFirstLog = true; // 首次日志标记
}

// 字符串转换辅助函数
std::wstring s2ws(const std::string& s) {
    int len;
    int slength = (int)s.length() + 1;
    len = MultiByteToWideChar(CP_ACP, 0, s.c_str(), slength, 0, 0);
    std::wstring buf;
    buf.resize(len);
    MultiByteToWideChar(CP_ACP, 0, s.c_str(), slength, &buf[0], len);
    return buf;
}

std::string ws2s(const std::wstring& ws) {
    int len;
    int wlength = (int)ws.length() + 1;
    len = WideCharToMultiByte(CP_ACP, 0, ws.c_str(), wlength, 0, 0, 0, 0);
    std::string buf;
    buf.resize(len);
    WideCharToMultiByte(CP_ACP, 0, ws.c_str(), wlength, &buf[0], len, 0, 0);
    return buf;
}

// 获取父进程名称
std::wstring getParentProcessName() {
    DWORD parentPid = 0;
    DWORD currentPid = GetCurrentProcessId();
    HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);

    if (hSnapshot == INVALID_HANDLE_VALUE) return L"";

    PROCESSENTRY32 pe;
    ZeroMemory(&pe, sizeof(pe));
    pe.dwSize = sizeof(PROCESSENTRY32);

    if (Process32First(hSnapshot, &pe)) {
        do {
            if (pe.th32ProcessID == currentPid) {
                parentPid = pe.th32ParentProcessID;
                break;
            }
        } while (Process32Next(hSnapshot, &pe));
    }

    CloseHandle(hSnapshot);

    if (parentPid != 0) {
        HANDLE hParent = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, parentPid);
        if (hParent) {
            WCHAR exeName[MAX_PATH] = {0};
            GetModuleFileNameExW(hParent, NULL, exeName, MAX_PATH);
            CloseHandle(hParent);
            return std::wstring(exeName);
        }
    }
    return L"";
}

// 判断是否需要显示控制台
bool shouldShowConsole() {
    std::wstring parentName = getParentProcessName();
    std::transform(parentName.begin(), parentName.end(), parentName.begin(), ::tolower);
    return parentName.find(L"cmd.exe") != std::wstring::npos ||
           parentName.find(L"powershell.exe") != std::wstring::npos ||
           parentName.find(L"wt.exe") != std::wstring::npos;
}

// 动态分配控制台
void allocateConsole() {
    if (!AttachConsole(ATTACH_PARENT_PROCESS)) {
        AllocConsole();
    }

    FILE* fDummy;
    freopen_s(&fDummy, "CONOUT$", "w", stdout);
    freopen_s(&fDummy, "CONOUT$", "w", stderr);
    freopen_s(&fDummy, "CONIN$", "r", stdin);
}

// 隐藏控制台窗口
void hideConsole() {
    HWND hwnd = GetConsoleWindow();
    if (hwnd != NULL) {
        ShowWindow(hwnd, SW_HIDE);
    }
}

// 获取当前时间字符串
std::wstring getCurrentTimeString() {
    time_t now = time(0);
    struct tm tstruct;
    wchar_t buf[80];
    localtime_s(&tstruct, &now);
    wcsftime(buf, sizeof(buf), L"%Y-%m-%d %H:%M:%S", &tstruct);
    return std::wstring(buf);
}

// 创建目录
bool createDirectoryRecursive(const std::wstring& path) {
    std::wstring currentPath;
    for (size_t i = 0; i < path.size(); ++i) {
        if (path[i] == L'\\' || path[i] == L'/') {
            if (!currentPath.empty() && !PathIsDirectoryW(currentPath.c_str())) {
                if (!CreateDirectoryW(currentPath.c_str(), NULL) && GetLastError() != ERROR_ALREADY_EXISTS) {
                    return false;
                }
            }
        }
        currentPath += path[i];
    }

    if (!currentPath.empty() && !PathIsDirectoryW(currentPath.c_str())) {
        if (!CreateDirectoryW(currentPath.c_str(), NULL) && GetLastError() != ERROR_ALREADY_EXISTS) {
            return false;
        }
    }
    return true;
}

// 修改logMessage函数，支持同时输出到日志和控制台
void logMessage(const std::wstring &msg, bool isError = false) {
    // 生成带时间戳的消息（日志和控制台共用）
    std::wstring timestamp = L"[" + getCurrentTimeString() + L"] ";
    std::wstring fullMsg = timestamp + msg;

    // 1. 输出到日志（如果启用）
    if (LogConfig::enabled) {
        if (LogConfig::isFirstLog) {
            if (PathFileExistsW(LogConfig::path.c_str())) {
                DeleteFileW(LogConfig::path.c_str());
            }
            LogConfig::isFirstLog = false;
        }

        // 确保日志目录存在
        std::wstring logDir = LogConfig::path.substr(0, LogConfig::path.find_last_of(L"/\\"));
        if (!logDir.empty() && !PathIsDirectoryW(logDir.c_str())) {
            if (!createDirectoryRecursive(logDir)) {
                std::wcerr << L"无法创建日志目录: " << logDir << std::endl;
                return;
            }
        }

        std::wofstream logFile(LogConfig::path.c_str(), std::ios::app);
        if (logFile.is_open()) {
            logFile << fullMsg << L"\n";
            logFile.close();
        } else {
            std::wcerr << L"无法打开日志文件: " << LogConfig::path << std::endl;
        }
    }

    // 2. 输出到控制台（如果满足条件）
    if (g_verbose && g_consoleNeeded) {
        // 根据消息类型选择输出流（普通信息/错误信息）
        if (isError) {
            std::wcerr << fullMsg << std::endl;
            std::wcerr.flush();
        } else {
            std::wcout << fullMsg << std::endl;
            std::wcout.flush();
        }
    }
}

// 获取应用程序目录
std::wstring getApplicationDirectory() {
    WCHAR path[MAX_PATH];
    GetModuleFileNameW(NULL, path, MAX_PATH);
    std::wstring::size_type pos = std::wstring(path).find_last_of(L"\\/");
    return std::wstring(path).substr(0, pos);
}

// 构建符合Windows要求的宽字符环境变量块
std::vector<WCHAR> buildEnvBlock() {
    std::vector<WCHAR> envBlock;
    WCHAR* env = GetEnvironmentStringsW();

    if (env) {
        WCHAR* current = env;
        while (*current != L'\0') {
            // 复制环境变量
            while (*current != L'\0') {
                envBlock.push_back(*current);
                current++;
            }
            envBlock.push_back(L'\0');
            current++;
        }
        FreeEnvironmentStringsW(env);
    }

    // 添加终止符
    envBlock.push_back(L'\0');
    return envBlock;
}

// 更新环境变量PATH
void updateEnvironmentPath(const std::wstring& newPaths) {
    WCHAR originalPath[MAX_PATH * 4] = {0};
    DWORD pathLen = GetEnvironmentVariableW(L"PATH", originalPath, MAX_PATH * 4);

    std::wstring updatedPath = newPaths;
    if (pathLen > 0) {
        updatedPath += L";" + std::wstring(originalPath);
    }

    SetEnvironmentVariableW(L"PATH", updatedPath.c_str());
}

// 验证环境变量块内容（调试用）
void logEnvBlock(const std::vector<WCHAR> &envBlock) {
    logMessage(L"环境变量块内容：");
    const WCHAR *ptr = envBlock.data();
    while (*ptr != L'\0' || *(ptr+1) != L'\0') {
        if (*ptr != L'\0') {
            logMessage(L"  " + std::wstring(ptr));
        }
        ptr++;
        while (*ptr != L'\0') ptr++;
        ptr++;
    }
}

// 显示帮助信息
void printHelp() {
    std::wcout << APP_NAME << L" " << APP_VERSION << std::endl;
    std::wcout << L"用法: launcher [选项]" << std::endl << std::endl;
    std::wcout << L"日志控制选项:" << std::endl;
    std::wcout << L"  --log-enable    本次执行启用日志" << std::endl;
    std::wcout << L"  --log-disable   本次执行禁用日志" << std::endl;
    std::wcout << L"  --log-path <路径> 本次执行指定日志路径" << std::endl << std::endl;
    std::wcout << L"其他选项:" << std::endl;
    std::wcout << L"  -h, --help           显示此帮助信息" << std::endl;
    std::wcout << L"  -v, --version        显示程序版本信息" << std::endl;
    std::wcout << L"  --verbose            显示详细启动过程" << std::endl;
    std::wcout.flush(); // 强制刷新
}

// 显示版本信息
void printVersion() {
    std::wcout << APP_NAME << L" 版本 " << APP_VERSION << std::endl;
    std::wcout << L"Copyright (C) 2024 保留所有权利" << std::endl;
    std::wcout.flush(); // 强制刷新
}

// 使用标准main函数作为入口（彻底避开WinMain问题）
int main() {
    std::cout<<"launcher开始"<<std::endl;
    // 新增：设置本地化，支持宽字符输出
    setlocale(LC_ALL, "");


    // 判断是否需要显示控制台
    bool consoleNeeded = shouldShowConsole();
    if (consoleNeeded) {
        allocateConsole();  // 命令行启动时显示控制台
    } else {
        hideConsole();      // 双击启动时隐藏控制台
    }

    // 解析命令行参数（从系统获取）
    LPWSTR cmdLine = GetCommandLineW();
    int argc = 0;
    LPWSTR* argv = CommandLineToArgvW(cmdLine, &argc);

    bool showHelp = false;
    bool showVersion = false;
    bool verbose = false;
    bool tempLogEnabled = false;
    bool tempLogDisabled = false;
    std::wstring tempLogPath;

    // 设置默认日志路径
    std::wstring appDir = getApplicationDirectory();
    LogConfig::path = appDir + L"\\launcher.log";

    // 关键修改：从i=1开始解析（跳过argv[0]程序名）
    for (int i = 1; i < argc; ++i) {
        std::wstring arg = argv[i];
        if (arg == L"-h" || arg == L"--help") {
            showHelp = true;
        } else if (arg == L"-v" || arg == L"--version") {
            showVersion = true;
        } else if (arg == L"--verbose") {
            verbose = true;
        } else if (arg == L"--log-enable") {
            tempLogEnabled = true;
        } else if (arg == L"--log-disable") {
            tempLogDisabled = true;
        } else if (arg == L"--log-path") {
            if (i + 1 < argc) {
                tempLogPath = argv[++i];
            } else {
                if (consoleNeeded) {
                    std::wcerr << L"错误: --log-path 需要指定路径参数" << std::endl;
                    std::wcerr.flush(); // 强制刷新输出
                }
                LocalFree(argv);
                return 1;
            }
        } else {
            if (consoleNeeded) {
                std::wcerr << L"未知参数: " << arg << L" 使用 -h 查看帮助" << std::endl;
                std::wcerr.flush(); // 强制刷新输出
            }
            LocalFree(argv);
            return 1;
        }
    }
    LocalFree(argv);

    // 解析命令行参数后，为全局变量赋值
    g_verbose = verbose;
    g_consoleNeeded = consoleNeeded;

    // 处理帮助和版本请求（添加刷新输出）
    if (showHelp) {
        if (consoleNeeded) {
            printHelp();
        }
        return 0;
    }
    if (showVersion) {
        if (consoleNeeded) {
            printVersion();
        }
        return 0;
    }

    // 应用临时日志配置
    if (tempLogEnabled) LogConfig::enabled = true;
    if (tempLogDisabled) LogConfig::enabled = false;
    if (!tempLogPath.empty()) {
        LogConfig::path = tempLogPath;
    }

    // 确保日志目录存在
    std::wstring logDir = LogConfig::path.substr(0, LogConfig::path.find_last_of(L"/\\"));
    if (!logDir.empty() && LogConfig::enabled && !PathIsDirectoryW(logDir.c_str())) {
        if (!createDirectoryRecursive(logDir)) {
            if (consoleNeeded) {
                std::wcerr << L"无法创建日志目录: " << logDir << std::endl;
            }
            LogConfig::enabled = false;
        }
    }

    // 开始日志记录
    logMessage(L"=== 启动程序开始运行 ===");
    logMessage(L"程序目录: " + appDir);
    logMessage(L"当前日志配置: 启用=" + (LogConfig::enabled ? std::wstring(L"是") : std::wstring(L"否")) +
               L", 路径=" + LogConfig::path);
    if (verbose) logMessage(L"详细模式已启用");

    // 路径处理
    std::wstring mainExePath = appDir + L"\\bin\\UToolBox.exe";
    std::wstring libDir = appDir + L"\\lib";
    std::wstring pluginDir = appDir + L"\\plugin";

    logMessage(L"主程序路径: " + mainExePath);
    if (verbose) {
        logMessage(L"lib目录: " + libDir);
        logMessage(L"plugin目录: " + pluginDir);
    }

    // 验证文件/目录
    if (!PathFileExistsW(mainExePath.c_str())) {
        logMessage(L"错误: 主程序不存在");
        return 1;
    }
    if (!PathIsDirectoryW(libDir.c_str())) {
        logMessage(L"错误: lib目录不存在");
        return 1;
    }

    // 更新环境变量PATH
    std::wstring newPaths = libDir + L";" + pluginDir;
    updateEnvironmentPath(newPaths);


    if (verbose) {
        WCHAR currentPath[MAX_PATH * 4] = {0};
        GetEnvironmentVariableW(L"PATH", currentPath, MAX_PATH * 4);
        logMessage(L"设置环境变量PATH: " + std::wstring(currentPath));
    } else {
        logMessage(L"设置环境变量PATH: 已更新");
    }



    // 构建环境变量块
    auto envBlock = buildEnvBlock();
    if (verbose)logEnvBlock(envBlock);



    // 启动主程序
    STARTUPINFOW si;
    ZeroMemory(&si, sizeof(si));
    si.cb = sizeof(STARTUPINFOW);
    si.dwFlags = STARTF_USESHOWWINDOW;
    si.wShowWindow = SW_SHOW;

    PROCESS_INFORMATION pi;
    ZeroMemory(&pi, sizeof(pi));

    BOOL success = CreateProcessW(
        mainExePath.c_str(),
        NULL,
        NULL,
        NULL,
        FALSE,
        (consoleNeeded ? CREATE_NEW_PROCESS_GROUP : CREATE_NEW_PROCESS_GROUP | DETACHED_PROCESS) |
            CREATE_UNICODE_ENVIRONMENT,
        envBlock.data(),
        appDir.c_str(),
        &si,
        &pi
        );

    if (!success) {
        DWORD errorCode = GetLastError();
        logMessage(L"错误: 主程序启动失败，错误码: " + std::to_wstring(errorCode));
        return 1;
    }

    // 等待主程序初始化完成（短暂延迟，确保资源交接）
    Sleep(100);

    // 清理句柄
    CloseHandle(pi.hProcess);
    CloseHandle(pi.hThread);

    logMessage(L"成功: 主程序启动，进程ID - " + std::to_wstring(pi.dwProcessId));
    logMessage(L"=== 启动程序完成任务，退出运行 ===");

    // 命令行环境下，显式释放控制台关联
    if (consoleNeeded) {
        FreeConsole(); // 解除与父控制台的绑定
    }
    std::cout<<"launcher结束"<<std::endl;

    return 0;
}
